package com.baidu.sggc.core.common.utils;

import com.baidu.sggc.entity.AuditLog;
import com.baidu.sggc.service.AuditLogService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;

/**
 * 审计日志工具类
 */
@Slf4j
@Component
public class AuditLogUtil {

    @Autowired
    private AuditLogService auditLogService;

    /**
     * 记录审计日志 - 从请求头获取信息
     */
    public void recordAuditLog(String userId, String userName, String module,
                               String auditObject, String operation, String message) {
        recordAuditLog(userId, userName, module, auditObject, operation, message, "操作成功");
    }

    /**
     * 记录审计日志 - 从请求头获取信息（带操作状态）
     */
    public void recordAuditLog(String userId, String userName, String module,
                               String auditObject, String operation, String message, String operateState) {
        try {
            // 获取当前请求
            ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            if (attributes == null) {
                log.warn("无法获取当前请求上下文，跳过审计日志记录");
                return;
            }

            HttpServletRequest request = attributes.getRequest();

            // 检查是否需要审计
            String needAudit = request.getHeader("X-Bce-Audit-Need-Audit");
            if (!"true".equals(needAudit)) {
                return;
            }

            // 获取菜单路径（必填字段）
            String menuPath = request.getHeader("X-Bce-Audit-Menu-Path");
            if (menuPath == null || menuPath.trim().isEmpty()) {
                log.warn("菜单路径为空，跳过审计日志记录");
                return;
            }

            String decodedMenuPath = menuPath;

            try {
                decodedMenuPath = URLDecoder.decode(menuPath, StandardCharsets.UTF_8.name());
                log.info("解码后的菜单路径: {}", decodedMenuPath);
                // 后续逻辑使用 decodedMenuPath
            } catch (Exception e) {
                log.error("菜单路径解码失败", e);
            }

            // 构建审计日志
            AuditLog auditLog = buildAuditLog(userId, userName, module, auditObject,
                    operation, message, request, decodedMenuPath, operateState);

            // 异步保存日志
            saveAuditLogAsync(auditLog);

        } catch (Exception e) {
            log.error("记录审计日志失败", e);
        }
    }

    /**
     * 记录审计日志 - 手动指定参数（适用于登录、下载等特殊场景）
     */
    public void recordAuditLog(String userId, String userName, String module,
                               String auditObject, String operation, String message,
                               String menuPath, String platform, String eventType, String operateState) {
        try {
            // 验证必填字段
            if (userId == null || userName == null || module == null || auditObject == null ||
                    operation == null || menuPath == null || operateState == null) {
                log.warn("审计日志必填字段不能为空，跳过记录");
                return;
            }

            ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            HttpServletRequest request = null;
            if (attributes != null) {
                request = attributes.getRequest();
            }

            AuditLog auditLog = buildAuditLog(userId, userName, module, auditObject,
                    operation, message, request, menuPath, operateState);

            // 设置特殊参数
            if (platform != null) {
                auditLog.setPlatform(platform);
            }
            if (eventType != null) {
                auditLog.setEventType(eventType);
            }

            saveAuditLogAsync(auditLog);

        } catch (Exception e) {
            log.error("记录审计日志失败", e);
        }
    }

    /**
     * 记录下载审计日志
     */
    public void recordDownloadAuditLog(String userId, String userName, String fileName,
                                       String menuPath, boolean success) {
        try {
            ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            HttpServletRequest request = null;
            if (attributes != null) {
                request = attributes.getRequest();
            }

            String operateState = success ? "操作成功" : "操作失败";
            String downloadMessage = success ? ("下载文件成功: " + fileName) : ("下载文件失败: " + fileName);

            // 如果menuPath为空，使用默认值
            String finalMenuPath = (menuPath != null && !menuPath.trim().isEmpty()) ? menuPath : "文件管理>文件下载";

            AuditLog auditLog = buildAuditLog(userId, userName, "文件管理", fileName,
                    "download", downloadMessage, request, finalMenuPath, operateState);

            auditLog.setEventType("文件操作");

            saveAuditLogAsync(auditLog);

        } catch (Exception e) {
            log.error("记录下载审计日志失败", e);
        }
    }

    /**
     * 记录查询类操作审计日志（国网要求重点关注）
     */
    public void recordQueryAuditLog(String userId, String userName, String module,
                                    String auditObject, String queryConditions,
                                    String menuPath, String operation) {
        try {
            ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            if (attributes == null) {
                log.warn("无法获取当前请求上下文，跳过审计日志记录");
                return;
            }

            HttpServletRequest request = attributes.getRequest();

            // 检查是否需要审计
            String needAudit = request.getHeader("X-Bce-Audit-Need-Audit");
            if (!"true".equals(needAudit)) {
                // 对于查询操作，如果没有明确标识也进行记录
                if (queryConditions == null || queryConditions.trim().isEmpty()) {
                    return;
                }
            }

            // 获取菜单路径
            String finalMenuPath = request.getHeader("X-Bce-Audit-Menu-Path");
            if (finalMenuPath == null || finalMenuPath.trim().isEmpty()) {
                finalMenuPath = menuPath;
            }
            if (finalMenuPath == null || finalMenuPath.trim().isEmpty()) {
                log.warn("查询操作菜单路径为空，跳过审计日志记录");
                return;
            }

            // 扩展数据
            String extendData = buildQueryExtendData(queryConditions, request);

            AuditLog auditLog = buildAuditLog(userId, userName, module, auditObject,
                    operation, "查询操作", request, finalMenuPath, "操作成功");

            auditLog.setEventType("查询操作");
            auditLog.setExtendData(extendData);

            saveAuditLogAsync(auditLog);
        } catch (Exception e) {
            log.error("记录查询审计日志失败", e);
        }
    }

    /**
     * 构建查询操作的扩展数据
     */
    private String buildQueryExtendData(String queryConditions, HttpServletRequest request) {
        StringBuilder extendData = new StringBuilder();
        extendData.append("{");

        // 查询条件
        if (queryConditions != null && !queryConditions.trim().isEmpty()) {
            extendData.append("\"queryConditions\":\"").append(queryConditions.replace("\"", "\\\"")).append("\",");
        }

        // 请求参数
        if (request != null) {
            StringBuilder params = new StringBuilder();
            request.getParameterMap().forEach((key, values) -> {
                if (params.length() > 0) {
                    params.append(",");
                }
                params.append("\"").append(key).append("\":\"").append(String.join(",", values)).append("\"");
            });

            if (params.length() > 0) {
                extendData.append("\"requestParams\":{").append(params.toString()).append("},");
            }
        }

        // 移除最后的逗号
        if (extendData.length() > 1 && extendData.charAt(extendData.length() - 1) == ',') {
            extendData.setLength(extendData.length() - 1);
        }

        extendData.append("}");
        return extendData.toString();
    }
    /**
     * 构建审计日志对象
     */
    public AuditLog buildAuditLog(String userId, String userName, String module,
                                   String auditObject, String operation, String message,
                                   HttpServletRequest request, String menuPath, String operateState) {
        AuditLog auditLog = new AuditLog();

        // 必填字段验证和设置
        if (userId == null || userName == null || module == null || auditObject == null ||
                operation == null || menuPath == null || operateState == null) {
            throw new IllegalArgumentException("审计日志必填字段不能为空");
        }

        // 基本信息（必填）
        auditLog.setUserId(userId);
        auditLog.setUserName(userName);
        auditLog.setModule(module);
        auditLog.setAuditObject(auditObject);
        auditLog.setOperation(operation);
        auditLog.setOperateTime(LocalDateTime.now());
        auditLog.setMenuPath(menuPath);
        auditLog.setOperateState(operateState);

        // 可选字段
        auditLog.setMessage(message);

        // 从请求中获取信息
        if (request != null) {
            auditLog.setAccessAddress(getClientIpAddress(request));
            auditLog.setPlatform(determinePlatformFromRequest(request));
            auditLog.setAppName(getAppName(request));
        } else {
            auditLog.setAccessAddress("unknown");
            auditLog.setPlatform("unknown");
            auditLog.setAppName("unknown");
        }

        // 确保AppName不为空（必填字段）
        if (auditLog.getAppName() == null || auditLog.getAppName().trim().isEmpty()) {
            auditLog.setAppName("bml-scheduler"); // 默认应用名称
        }

        return auditLog;
    }

    /**
     * 获取客户端IP地址
     */
    private String getClientIpAddress(HttpServletRequest request) {
        String xForwardedFor = request.getHeader("X-Forwarded-For");
        if (xForwardedFor != null && !xForwardedFor.isEmpty() && !"unknown".equalsIgnoreCase(xForwardedFor)) {
            return xForwardedFor.split(",")[0].trim();
        }

        String xRealIP = request.getHeader("X-Real-IP");
        if (xRealIP != null && !xRealIP.isEmpty() && !"unknown".equalsIgnoreCase(xRealIP)) {
            return xRealIP;
        }

        return request.getRemoteAddr();
    }

    /**
     * 判断平台类型（根据规范：lite，ai_plat，qianfan_plat）
     */
    private String determinePlatformFromRequest(HttpServletRequest request) {
        // 优先从请求头获取平台信息
        String platform = request.getHeader("X-Platform");
        if (platform != null && !platform.trim().isEmpty()) {
            return platform;
        }

        // 从User-Agent判断
        String userAgent = request.getHeader("User-Agent");
        if (userAgent == null) {
            return "lite"; // 默认值
        }

        userAgent = userAgent.toLowerCase();
        if (userAgent.contains("qianfan")) {
            return "qianfan_plat";
        } else if (userAgent.contains("ai")) {
            return "ai_plat";
        } else {
            return "lite";
        }
    }

    /**
     * 获取应用名称（必填字段）
     */
    private String getAppName(HttpServletRequest request) {
        // 优先从请求头获取
        String appName = request.getHeader("X-App-Name");
        if (appName != null && !appName.trim().isEmpty()) {
            return appName;
        }

        // 从Host获取
        String host = request.getHeader("Host");
        if (host != null && !host.trim().isEmpty()) {
            return host.split("\\.")[0]; // 取域名第一部分作为应用名
        }

        // 默认值，建议根据实际部署环境配置
        return "bml-scheduler";
    }

    /**
     * 异步保存审计日志
     */
    public void saveAuditLogAsync(AuditLog auditLog) {
        try {
            if (auditLog.getEventType() == null) {
                auditLog.setEventType("businessEvent");
            }
            auditLog.setAppName("custom-portal");
            auditLogService.save(auditLog);
        } catch (Exception e) {
            log.error("保存审计日志到数据库失败", e);
        }
    }
}
